#ifndef MODBUSMASTER_H
#define MODBUSMASTER_H

#include <QObject>
#include <QSerialPort>
#include <QByteArray>
#include <QVector>
#include <QMutex>

/**
 * @brief Modbus RTU 主站类
 * 实现 Modbus RTU 协议，封装 0x03 功能码读取保持寄存器
 */
class ModbusMaster : public QObject
{
    Q_OBJECT

public:
    /**
     * @brief Modbus 响应结果结构体
     */
    struct ModbusResponse
    {
        bool success;          ///< 是否成功
        quint8 slaveId;        ///< 从站地址
        quint8 functionCode;   ///< 功能码
        QVector<quint16> data; ///< 寄存器数据
        QString errorMessage;  ///< 错误信息
    };

    explicit ModbusMaster(QSerialPort *serialPort, QObject *parent = nullptr);
    ~ModbusMaster();

    /**
     * @brief 读取保持寄存器 (0x03功能码)
     * @param slaveId 从站地址 (1-120)
     * @param startAddress 起始寄存器地址
     * @param quantity 读取数量（寄存器个数）
     * @param timeout 超时时间（毫秒）
     * @return Modbus响应结果
     */
    ModbusResponse readHoldingRegisters(quint8 slaveId, quint16 startAddress,
                                        quint16 quantity, int timeout = 500);

    /**
     * @brief 读取PM2220电表的6个基础参数（Ua, Ub, Uc, Ia, Ib, Ic）
     * @param slaveId 从站地址 (1-120)
     * @param timeout 超时时间（毫秒）
     * @return Modbus响应结果
     */
    ModbusResponse readMeterData(quint8 slaveId, int timeout = 500);

    /**
     * @brief 设置串口对象
     * @param serialPort 串口对象指针
     */
    void setSerialPort(QSerialPort *serialPort);

    /**
     * @brief 获取串口对象
     * @return 串口对象指针
     */
    QSerialPort *serialPort() const { return m_serialPort; }

signals:
    /**
     * @brief 接收到响应信号
     * @param slaveId 从站地址
     * @param data 寄存器数据
     */
    void responseReceived(quint8 slaveId, const QVector<quint16> &data);

    /**
     * @brief 通信错误信号
     * @param slaveId 从站地址
     * @param errorMessage 错误信息
     */
    void communicationError(quint8 slaveId, const QString &errorMessage);

private:
    /**
     * @brief 构建Modbus RTU请求帧
     * @param slaveId 从站地址
     * @param functionCode 功能码
     * @param startAddress 起始地址
     * @param quantity 数量
     * @return 请求帧数据
     */
    QByteArray buildRequest(quint8 slaveId, quint8 functionCode,
                            quint16 startAddress, quint16 quantity);

    /**
     * @brief 解析Modbus RTU响应帧
     * @param response 响应数据
     * @return 解析结果
     */
    ModbusResponse parseResponse(const QByteArray &response);

    /**
     * @brief 计算CRC16校验
     * @param data 数据
     * @return CRC16校验值
     */
    quint16 calculateCRC16(const QByteArray &data);

    /**
     * @brief 验证CRC16校验
     * @param data 数据（包含CRC）
     * @return 是否校验通过
     */
    bool verifyCRC16(const QByteArray &data);

    /**
     * @brief 等待响应数据
     * @param expectedLength 期望的数据长度
     * @param timeout 超时时间（毫秒）
     * @return 接收到的数据
     */
    QByteArray waitForResponse(int expectedLength, int timeout);

private:
    QSerialPort *m_serialPort; ///< 串口对象
    QMutex m_mutex;            ///< 互斥锁，保证线程安全

    // Modbus RTU 常量
    static constexpr quint8 FUNCTION_CODE_READ_HOLDING_REGISTERS = 0x03; // 读取保持寄存器功能码
    static constexpr int MIN_RESPONSE_LENGTH = 5;                        // 最小响应长度：地址(1) + 功能码(1) + 字节数(1) + CRC(2)
};

#endif // MODBUSMASTER_H
